package com.cinyi.ormx.android.dao;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.database.Cursor;

import com.cinyi.ormlite.core.BaseModel;
import com.cinyi.ormlite.core.TableConfig;
import com.cinyi.ormlite.core.TableConfigCache;
import com.cinyi.ormlite.dao.DatabaseAdapter;
import com.cinyi.ormlite.dao.SQLModel;
import com.cinyi.ormx.android.context.LogHelper;

/**
 * jdbc操作
 * @author penghui
 *
 */
@SuppressWarnings("rawtypes")
public class AndroidDatabaseAdapter<T extends BaseModel<?>> extends DatabaseAdapter<T>{
    /**
     * LOG
     */
	public static final int YES = 1 ;
	public static final int NO = 0 ;
	
	private DefaultSQLiteHelper jdbc ;
	
	public AndroidDatabaseAdapter(DefaultSQLiteHelper db){
		this.jdbc = db ;
	}
	
	public Integer executeSQL(String sql,List<Object> params) throws Exception {
		Object[] array = null ;
		if(params != null && params.size()>0){
			array = new Object[params.size()];
			params.toArray(array);
		}
		LogHelper.d("executeSQL:" +sql );
		jdbc.getWritableDatabase().execSQL(sql, array);  ;
		return 0 ;
	}
	

    public Cursor executeQuery(String sql,List<Object> params) throws Exception {
		LogHelper.d("executeQuery SQL:"+sql);
		String[] array = null ;
		if(params != null && params.size()>0){
			int size = params.size();
			array = new String[size];
			for(int i=0;i<size;i++){
				array[i] = params.get(i)==null?null:String.valueOf(params.get(i));
			}
		}
		
        Cursor cursor = jdbc.getReadableDatabase().rawQuery(sql, array);
        return cursor ;
    }

	@SuppressWarnings("unchecked")
	@Override
	public Integer executeSQL(SQLModel model) throws Exception {
		return executeSQL(model.getSql(), model.getData());
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> executeQuery(SQLModel<T> model) throws Exception {
		List<T> list = new ArrayList<T>();
		TableConfig cfg = TableConfigCache.getConfig(model.getClazz());
		Field[] fields = cfg.getFields();
		
        List<Object> params = model.getData();
        
        Cursor cursor = executeQuery(model.getSql(),params);
		Map<String,Integer> columnLables = createResultMeta(cursor);
		if(cursor!=null && cursor.moveToFirst()){
			do{
				T t = (T) model.getClazz().newInstance();
				createObject(t, columnLables , fields, cursor);
				list.add(t);
			}while(cursor.moveToNext());
			cursor.close();
			
		}
			
		
		return list;
		
	}

	
	@Override
	public Long count(SQLModel model) throws Exception {
		return null;
	}

	private Map<String,Integer> createResultMeta(Cursor rs) throws Exception{
		Map<String,Integer> keys = new  HashMap<String,Integer>();
		int count=rs.getColumnCount();
		for(int i=0;i<count;i++){
			String col = rs.getColumnName(i);
			keys.put(col,i);
		}
		
		return keys ;
	}
	
	/**
	 * 根据结果集初始化对象
	 */
	private void createObject(T t,Map<String,Integer> columnLabels , Field[] fields, Cursor rs)
			throws Exception,
			IllegalAccessException, InvocationTargetException {
		for (Field field : fields) {
			String propertyName = field.getName();
			Object paramVal = null;
			Class<?> clazzField = field.getType();
			
			if( !columnLabels.containsKey(propertyName)){
//				logg.debug("column not found  cfdsg:" + propertyName );
				continue ;
			}
			
			if (clazzField == String.class) {
				paramVal = rs.getString(rs.getColumnIndex(propertyName));
			} else if (clazzField == short.class || clazzField == Short.class) {
				paramVal = rs.getShort(rs.getColumnIndex(propertyName));
			} else if (clazzField == int.class || clazzField == Integer.class) {
				paramVal = rs.getInt(rs.getColumnIndex(propertyName));
			} else if (clazzField == long.class || clazzField == Long.class) {
				paramVal = rs.getLong(rs.getColumnIndex(propertyName));
			} else if (clazzField == float.class || clazzField == Float.class) {
				paramVal = rs.getFloat(rs.getColumnIndex(propertyName));
			} else if (clazzField == double.class || clazzField == Double.class) {
				paramVal = rs.getDouble(rs.getColumnIndex(propertyName));
			} else if (clazzField == boolean.class || clazzField == Boolean.class) {
				paramVal = rs.getInt(rs.getColumnIndex(propertyName)) == YES ;
			} else if (clazzField == byte.class || clazzField == Byte.class) {
				paramVal = rs.getShort(rs.getColumnIndex(propertyName));
			} else if (clazzField == char.class || clazzField == Character.class) {
				paramVal = rs.getShort(rs.getColumnIndex(propertyName));
			} else if (clazzField == Date.class) {
				paramVal = rs.getLong(rs.getColumnIndex(propertyName));//time~ms
			} else if (clazzField.isArray()) {
				paramVal = rs.getString(rs.getColumnIndex(propertyName)).split(",");	//以逗号分隔的字符串
			} 
			
			/**
			 * 
			 */
			if(paramVal == null){
			    continue ;
			}
			
			com.cinyi.ormlite.util.ReflectionUtils.setFieldValue(t, propertyName, paramVal);
			
//			Method setmethod = ReflectionUtils.getDeclaredMethod(t, addSetString(propertyName), t.getClass());
//            setmethod.invoke(t, paramVal);
			
		}
	}
	
	
}
